package morefun

//import org.apache.oro.text.regex.Pattern

import java.util.regex.Pattern
import java.net.{URLDecoder, URLEncoder}
import java.text.SimpleDateFormat
import java.util.Date

import scala.io.Source
import java.sql.{Connection, DriverManager, ResultSet};

 case class MFLinkLogger() {

  var ip: String = "";
  var time: String = "";
  var fileName: String = "";
  var verCode: String = "";
  var verName: String = "";
  var channel: String = "";
  var subChannel: String = "";
  var deviceId: String = "";

   def toLog(): String = {
     var strLog = "ip:" + ip + " time:" + time + " fileName:" + fileName + " verCode:" + verCode + " verName:" + verName;
     strLog += " channel:" + channel + " subChannel:" + subChannel + " deviceId:" + deviceId;
     return strLog;
   }
}

object MFLinkLogger {

  val line_test = """106.118.118.117 - - [13/Nov/2017:17:00:08 +0800] "GET /mflink/1.0/version.php?filename=MFLinkServer&vercode=0&vername=&type=release&channel=tpv&subchannel=sc-628&build=&md5=33b7e0dfa5226c1ad2d9f8720907367d&deviceName=MFLink-4988&deviceModel=65PFF5652&androidVersion=4.4.2&pixels=1920X1080&densityDpi=240&deviceUniqueID=d894c7414035d7d434623cd641578609&MFLinkStarterVersion=1.9.14 HTTP/1.1" 200 100 "-" "Dalvik/1.6.0 (Linux; U; Android 4.4.2; 65PFF5652 Build/KOT49H)" "-""""

  // 即系 Nginx Log 格式的正则
  val LOG_PATTERN = """(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})? (\S+) (\S+) (\[.+?\]) (\S+) (\S+)""".r

  // 获取所有参数的正则
  var PATTERN_PARAMS_MFLINK = """/mflink/1.0/version.php?(\S+)""".r

  /**
    *
    * URL 解码
    * @param value
    * @return
    */
  def urlDecode(value : String): String = {
    URLDecoder.decode(value, "UTF8");
  }

  def parseLogFile(filePath: String) {
    val file=Source.fromFile(filePath)
    for(line <- file.getLines)
    {
      try {
        var nginxLogger = parseLogLine(line);
        println("#-# NginxLogger::parseLogLine parseLogFile Logger = " + nginxLogger.toLog());
      }catch {
        case e: Exception => println("#-# NginxLogger::parseLogFile exception, model = " +  line);
      }
    }
    file.close
  }

  /**
    * 解析一行 Log，转换成 NginxLogger
    *
    * @param logLine
    * @return
    */
  def parseLogLine(logLine: String): MFLinkLogger = {

//    println("#-# NginxLogger::parseLogLine - start parse - " + logLine);

    // 获取 Log 中的基本信息
    val res = LOG_PATTERN.findFirstMatchIn(logLine)
    
    if (res == null || res.isEmpty) {
      throw new RuntimeException("#-# NginxLogger::parseLogLine - Cannot parse log line: " + logLine)
    }

    val m = res.get;

    var myLogger = new MFLinkLogger;

    myLogger.ip = m.group(1); // 正则表达式中第一个是 IP
    myLogger.time = m.group(4).replace("[","").replace("]",""); // 获取时间
    var params = PATTERN_PARAMS_MFLINK.findFirstMatchIn(m.group(6)) // 获取所有的参数

    if (params.isEmpty) {
      throw new RuntimeException("Cannot parse log line: " + params)
    }

//    var fileName = "";
//    var verCode = "";
//    var verName = "";
//    var channel = "";
//    var subChannel = "";
//    var deviceId = "";


    val params2 = params.get;

    val paramsList = params2.toString().split("&");

//    println("paramsList size = " + paramsList.size);

    // 把第一个参数中的 URL 地址去掉
    if (paramsList.size >= 1) {
      paramsList(0) = paramsList(0).replace("/mflink/1.0/version.php?","");
    }

    //遍历所有参数，设置对应的变量
    for(i <- 1 to paramsList.size) {

      if (paramsList(i - 1).startsWith("filename=")) {
        myLogger.fileName = urlDecode(paramsList(i - 1).replace("filename=",""));
      }
      else if (paramsList(i - 1).startsWith("vercode=")) {
        myLogger.verCode = urlDecode(paramsList(i - 1).replace("vercode=",""));
      }
      else if (paramsList(i - 1).startsWith("vername=")) {
        myLogger.verName = urlDecode(paramsList(i - 1).replace("vername=",""));
      }
      else if (paramsList(i - 1).startsWith("channel=")) {
        myLogger.channel = urlDecode(paramsList(i - 1).replace("channel=",""));
      }
      else if (paramsList(i - 1).startsWith("subchannel=")) {
        myLogger.subChannel = urlDecode(paramsList(i - 1).replace("subchannel=",""));
      }
      else if (paramsList(i - 1).startsWith("deviceUniqueID=")) {
        myLogger. deviceId = urlDecode(paramsList(i - 1).replace("deviceUniqueID=",""));
      }
//      println("#-# NginxLogger::parseLogLine paramsList = " + paramsList(i-1));
    }

    // 生成 MFLinkLogger 并且处理 model
//    new MFLinkLogger(ip, time, fileName, verCode, verName, channel, subChannel, deviceId);

    return myLogger;
  }

  def nowDate(): String = {
    val now: Date = new Date()
    val dateFormat: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS")
    val date = dateFormat.format(now)
    return date
  }

  def main(args: Array[String]) {

    val startTime = (new Date()).getTime();

    println("#-# start = " + nowDate());
    parseLogFile("/Users/wdy/Downloads/nginx_access_20171113.log");
//    parseLogFile("/Users/wdy/Downloads/daily.log.2017-08-10.log");
    val endTime = (new Date()).getTime();

    println("#-# end = " + nowDate());
    println("#-# duration = " + (endTime - startTime));

    // ----------
//    var nginxLogger = parseLogLine(line_test);
//    println(nginxLogger);
//
//    // Change to Your Database Config
//    val conn_str = "jdbc:mysql://114.55.2.82:3306/data_stat_test3?user=admin&password=W!nmess@2016"
//    // Load the driver
//    classOf[com.mysql.jdbc.Driver]
//    // Setup the connection
//    val conn = DriverManager.getConnection(conn_str)
//    try {
////      // Configure to be Read Only
////      val statement = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE)
////      // Execute Query
////      val rs = statement.executeQuery("SELECT * FROM daily_channel_stat ")
////      // Iterate Over ResultSet
////      while (rs.next) {
////        println(rs.getString("id"))
////        println(rs.getString("channel"))
////      }
//
//
//
//
//        val sql = new StringBuilder()
//          .append("INSERT INTO update(ip, time, verCode, verName, channel, subChannel,deviceId)")
//          .append("     VALUES(?, ?, ?, ?, ?, ?, ?,)")
//        val pstm = conn.prepareStatement(sql.toString())
//        pstm.setObject(1, "test2")
//        pstm.setObject(2, "2017-08-20 00:00:00")
//        pstm.setObject(3, "21")
//        pstm.setObject(4, "33")
//        pstm.setObject(5, "21")
//
//      val rs2 = pstm.executeUpdate()
//      //      val rs2 = statement.executeQuery("insert into daily_channel_stat " +
////        " (channel,create_time,increament_count, active_count, total) " +
////        " VALUES ('test2','2017-08-20 00:00:00','21','30','20');")
//
////      val rs2 = statement.executeQuery("update daily_channel_stat set " +
////        " channel = 'test2' " +
////        " where id = 1;")
//
//
//      println(" 影响行数：" + rs2)
//    } catch{
//      case e:Exception =>e.printStackTrace
//    }
//    finally {
//      conn.close
//    }

  }
}
